{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Regressão Linear Simples\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "## 1. Introdução\n",
    "\n",
    "A regressão linear é um método de predição com mais de 200 anos de idade. A regressão linear simples é um ótimo primeiro algoritmo de aprendizado de máquina para implementar, pois requer que você avalie as propriedades do seu conjunto de dados de treinamento, mas é simples o suficiente para que os iniciantes entendam. \n",
    "\n",
    "Neste tutorial, você descobrirá como implementar o algoritmo de regressão linear simples a partir do zero em Python.\n",
    "\n",
    "Depois de completar este tutorial, você saberá:\n",
    "\n",
    "1. Como estimar quantidades estatísticas a partir de dados de treinamento.\n",
    "2. Como estimar os coeficientes de regressão linear a partir dos dados.\n",
    "3. Como fazer previsões usando regressão linear para novos dados.\n",
    "\n",
    "### 1.1 Dataset - Seguro de Veículo Sueco\n",
    "\n",
    "Neste tutorial, usaremos o Dataset Swedish Auto Insurance. Este conjunto de dados envolve a previsão de pagamentos de reclamações totais.  Faça o download do conjunto de dados e guarde-o no seu diretório de trabalho atual com o nome do arquivo insurance.csv. \n",
    "\n",
    "Nota: talvez seja necessário converter a vírgula européia (,) para o ponto decimal (.). Você também precisará alterar o arquivo de variáveis separadas em espaço branco para formato CSV.\n",
    "\n",
    "### 1.2 Algoritmo de Regressão Linear Simples\n",
    "\n",
    "A regressão linear assume uma relação linear ou linha reta entre as variáveis de entrada (X) e a variável de saída única (y). Mais especificamente, essa saída (y) pode ser calculada a partir de uma combinação linear das variáveis de entrada (X). Quando existe uma única variável de entrada, o método é referido como uma regressão linear simples.\n",
    "\n",
    "Em regressão linear simples, podemos usar estatísticas sobre os dados de treinamento para estimar os coeficientes exigidos pelo modelo para fazer previsões em novos dados. A linha reta para um modelo de regressão linear simples pode ser escrita como:\n",
    "\n",
    "![alt text](images/regressao_linear_modelo.png \"\")\n",
    "                             \n",
    "Onde b0 e b1 são os coeficientes que devemos estimar a partir dos dados de treinamento. Uma vez que os coeficientes são conhecidos, podemos usar esta equação para estimar os valores de saída para y dado novos exemplos de entrada de x. Exige que você calcule propriedades estatísticas dos dados, como média, variância e covariância.\n",
    "\n",
    "Toda a álgebra foi dada e ficamos apenas com alguma aritmética para implementar a estimativa dos coeficientes de regressão linear simples. Resumidamente, podemos estimar os coeficientes da seguinte forma:\n",
    "\n",
    "![alt text](images/coeficientes_regressao_linear.png \"Coeficientes lineares\")\n",
    "\n",
    "Onde o i se refere ao valor do i-ésimo valor da entrada x ou saída y. Não se preocupe se isso não estiver claro agora, estas são as funções que implementaremos no tutorial.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Passos do Tutorial\n",
    "\n",
    "Este tutorial é dividido em cinco partes:\n",
    "\n",
    "1. Calcule Média e Variância. \n",
    "2. Calcule Covariância.\n",
    "3. Estimar Coeficientes.\n",
    "4. Faça previsões.\n",
    "5. Estudo de caso do dataset de seguro de automóvel sueco.\n",
    "\n",
    "Essas etapas lhe darão a base que você precisa para implementar e treinar modelos simples de regressão linear para seus próprios problemas de previsão.\n",
    "\n",
    "### 2.1 Calcule Média e Variância\n",
    "\n",
    "O primeiro passo é estimar a média e a variância das variáveis de entrada e saída dos dados de treinamento. A média de uma lista de números pode ser calculada como:\n",
    "\n",
    "![alt text](images/media.png \"Média\")\n",
    "\n",
    "Abaixo está uma função chamada mean () que implementa esse comportamento para uma lista de números."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Calculate the mean value of a list of numbers\n",
    "def mean(values):\n",
    "  return sum(values) / float(len(values))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "The variance is the sum squared difference for each value from the mean value. Variance for a list of numbers can be calculated as:\n",
    "\n",
    "![alt text](images/varianca.png \"Média\")\n",
    "\n",
    "Abaixo está uma função chamada variance () que calcula a variância de uma lista de números. Isto exige que a média da lista seja fornecida como um argumento, apenas não precisamos calcular mais de uma vez."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Calculate the variance of a list of numbers\n",
    "def variance(values, mean):\n",
    "  return sum([(x-mean)**2 for x in values])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercicio 1\n",
    "\n",
    "(a) Junte as duas funções acima e teste-as em um conjunto de dados pequeno dado. Utiloze como exemplo, o pequeno conjunto de dados de valores x e y.\n",
    "\n",
    "x |  y\n",
    "--| -\n",
    "1 | 1\n",
    "2 | 3\n",
    "4 | 3\n",
    "3 | 2\n",
    "5 | 5\n",
    "\n",
    "(b) Em seguida crie um gráfico onde voce plot esses pontos\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Média de valores de x = 3.0 | Variancia dos valores de x = 10.0\n",
      "----------------------\n",
      "Média de valores de y = 2.8 | Variancia dos valores de y = 8.8\n"
     ]
    }
   ],
   "source": [
    "## COLOQUE SEU CODIGO AQUI\n",
    "x=[1,2,4,3,5]\n",
    "y=[1,3,3,2,5]\n",
    "print('Média de valores de x = {} | Variancia dos valores de x = {}'.format(mean(x),variance(x,mean(x))))\n",
    "print('----------------------')\n",
    "print('Média de valores de y = {} | Variancia dos valores de y = {}'.format(mean(y),variance(y,mean(y))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "## FAÇA O PLOT DOS DADOS AQUI\n",
    "%matplotlib inline \n",
    "import matplotlib.pyplot as plt\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 Calcular Covariância\n",
    "\n",
    "A covariância de dois grupos de números descreve como esses números mudam juntos. A co-variância é uma generalização da correlação. A correlação descreve a relação entre dois grupos de números, enquanto a covariância pode descrever a relação entre dois ou mais grupos de números. Além disso, a covariância pode ser normalizada para produzir um valor de correlação. No entanto, podemos calcular a covariância entre duas variáveis da seguinte forma:\n",
    "\n",
    "![alt text](images/covarianca.png \"Covariancia\")\n",
    "\n",
    "\n",
    "Abaixo está uma função chamada *covariance()* que implementa esta estatística. Esta função baseia-se no passo anterior e leva as listas de valores x e y, bem como a média desses valores como argumentos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Calculate covariance between x and y\n",
    "def covariance(x, mean_x, y, mean_y):\n",
    "  covar = 0.0\n",
    "  for i in range(len(x)):\n",
    "    covar += (x[i] - mean_x) * (y[i] - mean_y)\n",
    "  return covar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercicio 2\n",
    "\n",
    "Teste o cálculo da covariância no mesmo pequeno conjunto de dados apresentado na\n",
    "seção anterior."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8.0\n"
     ]
    }
   ],
   "source": [
    "## COLOQUE SEU CODIGO AQUI\n",
    "print(covariance(x,mean(x),y,mean(y)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3 Estimativa dos Coeficientes \n",
    "\n",
    "Agora, devemos estimar os valores dos dois coeficientes em regressão linear simples. O primeiro é B1 que pode ser estimado como:\n",
    "\n",
    "![alt text](images/B1.png \"\")\n",
    "\n",
    "Podemos simplificar esta fórmula usando as funcões covariance e variance apresentadas acima, conforme a fórmula abaixo.\n",
    "\n",
    "![alt text](images/B1_simplificado.png \"\")\n",
    "\n",
    "Em seguida, precisamos estimar um valor para B0, também chamado de interceptação, pois controla o ponto inicial da linha onde ele intersecta o eixo y.\n",
    "\n",
    "![alt text](images/B0.png \"\")\n",
    "\n",
    "Mais uma vez, sabemos como estimar B1 e temos uma função para estimar a média (). Podemos juntar tudo isso em uma função denominada *coefficients ()* que leva o conjunto de dados como um argumento e retorna os coeficientes.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Calculate coefficients\n",
    "def coefficients(dataset):\n",
    "      x = [row[0] for row in dataset]\n",
    "      y = [row[1] for row in dataset]\n",
    "      x_mean, y_mean = mean(x), mean(y)\n",
    "      b1 = covariance(x, x_mean, y, y_mean) / variance(x, x_mean)\n",
    "      b0 = y_mean - b1 * x_mean\n",
    "      return [b0, b1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercicio 3\n",
    "\n",
    "Estenda o exercício anterior incluindo o cáculo dos coeficientes para os dados sintetizados.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "## COLOQUE SEU CODIGO AQUI"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2 Fazer previsões\n",
    "\n",
    "O modelo de regressão linear simples é uma linha definida pelos coeficientes estimados a partir dos dados de treinamento. Uma vez que os coeficientes são estimados, podemos usá-los para fazer previsões. A equação para fazer previsões com um modelo de regressão linear simples é a seguinte:\n",
    "\n",
    "![alt text](images/regressao_linear_modelo.png \"\")\n",
    "\n",
    "Abaixo é apresentada a função chamada *simple_linear_regression ()* que implementa a equação de predição para fazer previsões em um conjunto de dados de teste. Também une a estimativa dos coeficientes nos dados de treinamento das etapas acima. Os coeficientes preparados a partir dos dados de treinamento são usados para fazer previsões nos dados do teste, que são retornados."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def simple_linear_regression(train, test):\n",
    "  predictions = list()\n",
    "  b0, b1 = coefficients(train)\n",
    "  for row in test:\n",
    "    ypred = b0 + b1 * row[0]\n",
    "    predictions.append(ypred)\n",
    "  return predictions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para avaliar o modelo \n",
    " adicionaremos uma função para gerenciar a avaliação das previsões denominadas *evaluate_algorithm ()* e outra função para estimar o erro quadrático médio da raiz das previsões denominadas métrica *rmse_metric ()*. Veja as funções abaixo:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from math import sqrt\n",
    "\n",
    "# Calculate root mean squared error\n",
    "def rmse_metric(actual, predicted):\n",
    "  sum_error = 0.0\n",
    "  for i in range(len(actual)):\n",
    "    prediction_error = predicted[i] - actual[i]\n",
    "    sum_error += (prediction_error ** 2)\n",
    "  mean_error = sum_error / float(len(actual))\n",
    "  return sqrt(mean_error)\n",
    "\n",
    "# Evaluate regression algorithm on training dataset\n",
    "def evaluate_algorithm(dataset, algorithm):\n",
    "  test_set = list()\n",
    "  for row in dataset:\n",
    "    row_copy = list(row)\n",
    "    row_copy[-1] = None\n",
    "    test_set.append(row_copy)\n",
    "  predicted = algorithm(dataset, test_set)\n",
    "  print(predicted)\n",
    "  actual = [row[-1] for row in dataset]\n",
    "  rmse = rmse_metric(actual, predicted)\n",
    "  return rmse"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercicio 4 \n",
    "\n",
    "Agora junte tudo que foi criado para fazer previsões para o nosso conjunto de dados de teste."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "## COLOQUE SEU CODIGO AQUI"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercício 5\n",
    "\n",
    "Crie um scatter plot para mostrar as previsões como uma linha e compará-lo com o conjunto de dados original."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "## COLOQUE SEU CODIGO AQUI"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
